"""
    This file is part of django-simp.

    django-simp is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    django-simp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with django-simp.  If not, see <http://www.gnu.org/licenses/>.
"""

import sys, os, Image, ImageEnhance, uuid, shutil

from django.core import serializers
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseServerError
from django.shortcuts import render_to_response, get_object_or_404
from django.template.loader import render_to_string
from django.contrib.auth.decorators import user_passes_test
from django.utils import simplejson as json

#from SimpleJSONRPCServer import SimpleJSONRPCDispatcher

import settings

from simp.settings import *
from simp.models import *
from simp.mods import view
from simp.utils import *


# ...
""" 
This is the main Controller instance, it contains the instance module and handels the state of the application

"""
class Controller:
    instance = None
    modMgr = None
    image = None
    request = None
    _valid = True
    
    """ 
    object creation
    initialize the instance model and the things around
    """
    def __init__(self, request):
        self.request = request
        if request.session.get('simp_instance', False):
            inst_id = request.session['simp_instance']
            self.instance = Instance.objects.get(id=inst_id)
            self.modMgr = Module.objects
            self.image = self.instance.get_image()
        else:
            self._valid = False
        
    """ 
    helper methods 
    normaly id shut be more on the models
    """   
    def is_valid(self):
        return self._valid
    
    def register_rpc_methods(self, dispatcher):
        dispatcher.register_function(self.get_editor, 'editor')
        dispatcher.register_function(self.get_preset, 'preset')
        dispatcher.register_function(self.apply, 'apply')
        dispatcher.register_function(self.commit, 'commit')
        dispatcher.register_function(self.cancle, 'cancle');
        dispatcher.register_function(self.save, 'save');
    
    def create_next_image(self):
        pass
        
    def del_current_image(self):
        pass
    
    """ 
    published rpc methods
    Handels the default api of the application
    """
    def get_editor(self, module):
        retVal = {}
        #try:
        retVal["editor"] = self.modMgr.get_pymod(module).get_editor(self)
        retVal["image"] = self.image.get_image_dict()
        return retVal
    
    def get_preset(self, module, preset_order):
        retVal = {}
        retVal["module"] = module
        retVal["preset"] = preset_order
        preset = Preset.objects.get(module=module, order=preset_order)
        modPreset = preset.get_modpreset() 
        retVal["values"] = modPreset.to_dict()
        retVal["image"] = self.image.get_image_dict()
        return retVal
    
    def apply(self, module, preset_order, values):
        retVal = {}
        retVal["module"] = module
        retVal["preset"] = int(preset_order)
        retVal["values"] = self.modMgr.get_pymod(module).apply(self, int(preset_order), values)
        retVal["image"] = self.image.get_image_dict()
        return retVal
    
    def commit(self, module, preset_order, values):
        retVal = {}
        retVal["module"] = "default"
        newImg = self.image.create_next()
        newImg = self.modMgr.get_pymod(module).commit(self, preset_order, values, newImg)
        newImg.instance = self.instance
        newImg.preset = Preset.objects.get(module=module, order=preset_order)
        newImg.module = Module.objects.get(name=module)
        newImg.values = simplejson.dumps(values)
        newImg.commit = True
        newImg = self.image.apply_next(newImg)
        self.image = newImg
        retVal["editor"] = self.modMgr.get_default_editor(self)
        retVal["preset"] = self.modMgr.get_default_preset(self).to_dict();
        #self.image = self.instance.get_image()
        retVal["image"] = self.image.get_image_dict()
        return retVal
    
    def cancle(self):
        self.instance.deleteWholeInstance()
        del self.request.session['simp_instance'];
        retVal = {"callback": self.instance     .callback}
        return retVal
    
    def save(self):
        if self.instance.save_as == 'OVERRIDE':
            shutil.copy(self.image.get_image_filename(), self.instance.get_image_filename())
        elif self.instance.save_as.find('APPEND') >= 0:
            return "append"
        else:
            shutil.copy2(self.image.get_image_filename(), self.instance.save_as)
        return self.cancle()
    
#@user_passes_test(lambda u: u.has_perm('simp.use'), login_url=settings.LOGIN_URL)
def init(request):
    if request.session.get('simp_instance', False):
        ctrl = Controller(request)
        #try:
        #    sinst = Instance.objects.get(id=instance)  
        #except ObjectDoesNotExist:
        #    return HttpResponse("the simp instance with the id %s doesn't exist" % name)
        if (ctrl.instance.preset == None):
            has_toolbar = True
            #if sinst.embedded:
            #    hasToolbar = False
            #return HttpResponse(Module.objects.get(pk="crop").get_pymod().get_toolbar())
            return render_to_response('simp/editor.html', { 
                                'has_toolbar': has_toolbar,
                                'has_header': True,
                                'modules': Module.objects.all_pymods(),
                                'editor': view.get_editor(ctrl),
                                'baseUrl': '/simp/',
                                'instance_id': ctrl.instance.id,
                                'title': "simp image editor",
                                'user': request.user,
                                'file': simplejson.dumps(ctrl.image.get_image_dict()) })
        else:
            return render_to_response('simp/editor.html', {'model': ctrl.instance, 'editor': "Editor"})
    else:
        return HttpResponseRedirect("/simp/start/")

#@user_passes_test(lambda u: u.has_perm('simp.use'), login_url=settings.LOGIN_URL)
def start(request):
    simpInstance = Instance();
    simpInstance.id = str(uuid.uuid4())
    simpInstance.session = request.COOKIES[settings.SESSION_COOKIE_NAME];
    simpInstance.embedded = False;
    simpInstance.image = 'test.resized.png';
    simpInstance.preset = None;
    simpInstance.module = None;
    simpInstance.callback = "http://filesite.lo/"
    simpInstance.save();
    request.session['simp_instance'] = simpInstance.id;
    request.session.save();
    return HttpResponseRedirect('/simp/');


"""
    This is the default json rpc handler it register the controller and handels all requests
"""
#@user_passes_test(lambda u: u.has_perm('simp.use'), login_url=settings.LOGIN_URL)
def rpc_handler(request):
    controller = Controller(request)
    if controller.is_valid():         
        dispatcher = SimpleJSONRPCDispatcher(allow_none=False, encoding=None)
        controller.register_rpc_methods(dispatcher)
        response = HttpResponse()
        if len(request.POST):
            response.write(dispatcher.dispatch(request.raw_post_data))
        else:
            if request.GET.get("SMD", False):
                # shut be automatic generated. over method comments
                response.write(render_to_string("simp/jsonrpc.smd", {}))
            else:
                # replace with a templates
                response.write("<b>This is an JSON-RPC Service.</b><br>")
                response.write("You need to invoke it using an JSON-RPC Client!<br>")
                response.write("The following methods are available:<ul>")
                methods = dispatcher.system_listMethods()
        
                for method in methods:
                    # right now, my version of SimpleXMLRPCDispatcher always
                    # returns "signatures not supported"... :(
                    # but, in an ideal world it will tell users what args are expected
                    sig = dispatcher.system_methodSignature(method)
        
                    # this just reads your docblock, so fill it in!
                    help =  dispatcher.system_methodHelp(method)
        
                    response.write("<li><b>%s</b>: [%s] %s" % (method, sig, help))
        
                response.write("</ul>")
                response.write('<a href="http://www.djangoproject.com/"> <img src="http://media.djangoproject.com/img/badges/djangomade124x25_grey.gif" border="0" alt="Made with Django." title="Made with Django."></a>')
        response['Content-length'] = str(len(response.content))
        return response
    else:
        raise HttpResponseServerError(), "no valid simp request"
    

"""
get_scripts is the view which creates the basic scripts for the application,
It shut be loaded at every page where simp is used
this methods calls all modules get_script methods and adds the basic script of simp from the templates.
"""
def scripts(request):
    ctrl = Controller(request)
    if ctrl.is_valid():
        return render_to_response('simp/scripts/editor.js', { 
                                    'modules': ctrl.modMgr.all_pymods(),
                                    'base_url': '/simp/',
                                    'instance_id': ctrl.instance.id,
                                    'title': "simp image editor",
                                    'user': request.user,
                                    'file': ctrl.image.get_image_url() })
    else:
        raise HttpResponseServerError(), "no valid simp request"

